package com.seuic.device_implement;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;

import com.seuic.constants.ReceiptConstants;
import com.seuic.extra.receipt.ReceiptPrintListener;
import com.seuic.posdsdk.device_interface.ReceiptEngine;

import java.io.ByteArrayOutputStream;

public class ReceiptEngineImp extends BaseImplement implements ReceiptEngine {

    private static ReceiptEngineImp self;

    private ReceiptEngineImp() {
    }

    static ReceiptEngineImp getInstance() {
        if ( self == null ) {
            synchronized ( ReceiptEngineImp.class ) {
                if ( self == null ) {
                    self = new ReceiptEngineImp();
                }
            }
        }
        return self;
    }

    @Override
    public int clearBuffer() {
        if ( receipt == null ) {
            Log.e( LOG_TAG, "receipt == null" );
            setLastError( "Receipt Service Error" );
            return -1;
        }
        try {
            Bundle bundle = new Bundle();
            receipt.Init( bundle );
        } catch (RemoteException e) {
            Log.e( LOG_TAG, "RemoteException: " + e );
            setLastError( "Receipt Service Error" );
            return -2;
        }
        return 0;
    }

    @Override
    public int addTextLine(String text, Bundle params) {
        if ( text == null ) {
            setLastError( "Input Param Error" );
            return -1;
        }
        if ( receipt == null ) {
            Log.e( LOG_TAG, "receipt == null" );
            setLastError( "Receipt Service Error" );
            return -1;
        }
        if ( params == null ) {
            params = new Bundle();
        }
        params.putString( ReceiptConstants.TEXT, text );
        try {
            receipt.AddTextLine( params );
        } catch (RemoteException e) {
            Log.e( LOG_TAG, "RemoteException: " + e );
            setLastError( "Receipt Service Error" );
            return -2;
        }
        return 0;
    }

    @Override
    public int addBitmap(Bitmap bitmap, Bundle params) {
        if ( bitmap == null ) {
            setLastError( "Input Param Error" );
            return -1;
        }
        if ( receipt == null ) {
            Log.e( LOG_TAG, "receipt == null" );
            setLastError( "Receipt Service Error" );
            return -1;
        }
        if ( params == null ) {
            params = new Bundle();
        }
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress( Bitmap.CompressFormat.JPEG, 100, stream );
        params.putByteArray( ReceiptConstants.BITMAP, stream.toByteArray() );
        try {
            receipt.AddBitmap( params );
        } catch (RemoteException e) {
            Log.e( LOG_TAG, "RemoteException: " + e );
            setLastError( "Receipt Service Error" );
            return -2;
        }
        return 0;
    }

    @Override
    public int addQRCode(String content, Bundle params) {
        if ( content == null ) {
            setLastError( "Input Param Error" );
            return -1;
        }
        if ( receipt == null ) {
            Log.e( LOG_TAG, "receipt == null" );
            setLastError( "Receipt Service Error" );
            return -1;
        }
        if ( params == null ) {
            params = new Bundle();
        }
        params.putString( ReceiptConstants.QR_CODE, content );
        try {
            receipt.AddQRcode( params );
        } catch (RemoteException e) {
            Log.e( LOG_TAG, "RemoteException: " + e );
            setLastError( "Receipt Service Error" );
            return -2;
        }
        return 0;
    }

    @Override
    public int addBarcode(String content, Bundle params) {
        if ( content == null ) {
            setLastError( "Input Param Error" );
            return -1;
        }
        if ( receipt == null ) {
            Log.e( LOG_TAG, "receipt == null" );
            setLastError( "Receipt Service Error" );
            return -1;
        }
        if ( params == null ) {
            params = new Bundle();
        }
        params.putString( ReceiptConstants.BAR_CODE, content );
        try {
            receipt.AddBarcode( params );
        } catch (RemoteException e) {
            Log.e( LOG_TAG, "RemoteException: " + e );
            setLastError( "Receipt Service Error" );
            return -2;
        }
        return 0;
    }

    @Override
    public Bitmap getReceipt() {
        if ( receipt == null ) {
            Log.e( LOG_TAG, "receipt == null" );
            setLastError( "Receipt Service Error" );
            return null;
        }
        try {
            byte[] receiptData = receipt.GenerateReceipt();
            return BitmapFactory.decodeByteArray( receiptData, 0, receiptData.length );
        } catch (RemoteException e) {
            Log.e( LOG_TAG, "RemoteException: " + e );
            setLastError( "Receipt Service Error" );
            return null;
        }
    }

    private PrintReceiptCallback printReceiptCallback = null;

    @Override
    public void print(PrintReceiptCallback printReceiptCallback) {
        if ( null == printReceiptCallback ) {
            Log.e( LOG_TAG, "null == printReceiptCallback" );
            setLastError( "Input Param Error" );
            return;
        }
        this.printReceiptCallback = printReceiptCallback;
        if ( receipt == null ) {
            Log.e( LOG_TAG, "receipt == null" );
            printReceiptCallbackOnFail( "Receipt Service Error" );
            return;
        }
        try {
            int result = receipt.Print( new PosdReceiptPrintListener() );
            if ( result == -2 ) {
                printReceiptCallbackOnFail( "Battery Low" );
            } else if ( result < 0 ) {
                Log.e( LOG_TAG, "receipt.Print Failed: " + result );
                printReceiptCallbackOnFail( "Receipt Service Error" );
            }
        } catch (RemoteException e) {
            Log.e( LOG_TAG, "RemoteException: " + e );
            setLastError( "Receipt Service Error" );
        }
    }

    private void printReceiptCallbackOnFail(final String error ) {
        if ( printReceiptCallback == null ) {
            return;
        }
        handler.post(new Runnable() {
            @Override
            public void run() {
                printReceiptCallback.onFail( error );
            }
        });
    }

    private class PosdReceiptPrintListener extends ReceiptPrintListener.Stub {

        @Override
        public void OnSuccess() throws RemoteException {
            if ( printReceiptCallback == null ) {
                return;
            }
            handler.post(new Runnable() {
                @Override
                public void run() {
                    printReceiptCallback.onSuccess();
                }
            });
        }

        @Override
        public void OnFail(int returnCode) throws RemoteException {
            if ( returnCode == -2 ) {
                printReceiptCallbackOnFail( "Lack Paper" );
            } else {
                printReceiptCallbackOnFail( "Print Failed: " + returnCode );
            }
        }
    }
}
